package gui.body;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;

import javax.swing.JPanel;

import model.listener.DataListener;


public class BodyPaint extends JPanel implements DataListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1199555832864314657L;

	/**
	 * Limbs of the body
	 */
	Line2D[] neck;

	Line2D[] leftShoulder;
	Line2D[] leftElbow;
	Line2D[] leftHand;

	Line2D[] rightShoulder;
	Line2D[] rightElbow;
	Line2D[] rightHand;

	Line2D[] leftTorso;
	Line2D[] rightTorso; 

	Line2D[] leftHip;
	Line2D[] leftKnee;
	Line2D[] leftFoot;
	
	Line2D[] rightHip;
	Line2D[] rightKnee;
	Line2D[] rightFoot;
	
	Line2D[] hip;
	
	int maxUsers;
	
	Color[] colors;
	
	public BodyPaint(int maxUsers){
		this.maxUsers = maxUsers;
		neck = new Line2D[maxUsers];

		leftShoulder = new Line2D[maxUsers];
		leftElbow = new Line2D[maxUsers];
		leftHand = new Line2D[maxUsers];
		
		rightShoulder = new Line2D[maxUsers];
		rightElbow = new Line2D[maxUsers];
		rightHand = new Line2D[maxUsers];

		leftTorso = new Line2D[maxUsers];
		rightTorso = new Line2D[maxUsers];

		leftHip = new Line2D[maxUsers];
		leftKnee = new Line2D[maxUsers];
		leftFoot = new Line2D[maxUsers];

		rightHip = new Line2D[maxUsers];
		rightKnee = new Line2D[maxUsers];
		rightFoot = new Line2D[maxUsers];
		
		hip = new Line2D[maxUsers];
		
		neck = new Line2D[maxUsers];
		
		colors = new Color[maxUsers];
		
		for(int i = 0 ; i < maxUsers ; i++){
			colors[i] = new Color((float) Math.random(), (float) Math.random(), (float) Math.random());
		
			neck[i] = new Line2D.Double(0D, 0D, 0D, 0D);

			leftShoulder[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			leftElbow[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			leftHand[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			
			rightShoulder[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			rightElbow[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			rightHand[i] = new Line2D.Double(0D, 0D, 0D, 0D);

			leftTorso[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			rightTorso[i] = new Line2D.Double(0D, 0D, 0D, 0D);

			leftHip[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			leftKnee[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			leftFoot[i] = new Line2D.Double(0D, 0D, 0D, 0D);

			rightHip[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			rightKnee[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			rightFoot[i] = new Line2D.Double(0D, 0D, 0D, 0D);
			
			hip[i] = new Line2D.Double(0D, 0D, 0D, 0D);
		}
	}

	public void paintComponent(Graphics g) {
		float maxX = this.getWidth();
		float maxY = this.getHeight();
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, this.getWidth(), this.getHeight());

		Graphics2D graph = (Graphics2D) g;
		for(int i = 0 ; i < maxUsers ; i++){
			graph.setColor(colors[i]);

			graph.draw(normalize(neck[i], maxX, maxY));
	
			graph.draw(normalize(leftShoulder[i], maxX, maxY));
			graph.draw(normalize(leftElbow[i], maxX, maxY));
			graph.draw(normalize(leftHand[i], maxX, maxY));
	
			graph.draw(normalize(rightShoulder[i], maxX, maxY));
			graph.draw(normalize(rightElbow[i], maxX, maxY));
			graph.draw(normalize(rightHand[i], maxX, maxY));
	
			graph.draw(normalize(leftTorso[i], maxX, maxY));
			graph.draw(normalize(rightTorso[i], maxX, maxY));
	
			graph.draw(normalize(leftHip[i], maxX, maxY));
			graph.draw(normalize(leftKnee[i], maxX, maxY));
			graph.draw(normalize(leftFoot[i], maxX, maxY));
	
			graph.draw(normalize(rightHip[i], maxX, maxY));
			graph.draw(normalize(rightKnee[i], maxX, maxY));
			graph.draw(normalize(rightFoot[i], maxX, maxY));
	
			graph.draw(normalize(hip[i], maxX, maxY));
		}
	}

	@Override
	public synchronized void headData(float x, float y, float z, int userId,
			int time) {
		neck[userId].setLine(x, y, neck[userId].getX2(), neck[userId].getY2());
		this.repaint();
	}

	@Override
	public synchronized void leftAnklepData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void leftCollarData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void leftElbowData(float x, float y, float z,
			int userId, int time) {
		leftElbow[userId].setLine(leftElbow[userId].getX1(), leftElbow[userId].getY1(), x, y);
		leftHand[userId].setLine(x, y, leftHand[userId].getX2(), leftElbow[userId].getY2());
	}

	@Override
	public synchronized void leftFingertipData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void leftFootData(float x, float y, float z,
			int userId, int time) {
		leftFoot[userId].setLine(leftFoot[userId].getX1(), leftFoot[userId].getY1(), x, y);
	}

	@Override
	public synchronized void leftHandData(float x, float y, float z,
			int userId, int time) {
		leftHand[userId].setLine(leftHand[userId].getX1(), leftHand[userId].getY1(), x, y);
	}

	@Override
	public synchronized void leftHipData(float x, float y, float z, int userId,
			int time) {
		leftHip[userId].setLine(leftHip[userId].getX1(), leftHip[userId].getY1(), x, y);
		leftKnee[userId].setLine(x, y, leftKnee[userId].getX2(), leftKnee[userId].getY2());
		hip[userId].setLine(x, y, hip[userId].getX2(), hip[userId].getY2());
	}

	@Override
	public synchronized void leftKneeData(float x, float y, float z,
			int userId, int time) {
		leftKnee[userId].setLine(leftKnee[userId].getX1(), leftKnee[userId].getY1(), x, y);
		leftFoot[userId].setLine(x, y, leftFoot[userId].getX2(), leftFoot[userId].getY2());
	}

	@Override
	public synchronized void leftShoulderData(float x, float y, float z,
			int userId, int time) {
		leftShoulder[userId].setLine(leftShoulder[userId].getX1(), leftShoulder[userId].getY1(), x, y);
		leftElbow[userId].setLine(x,y,leftElbow[userId].getX2(),leftElbow[userId].getY2());
		leftTorso[userId].setLine(x, y, leftTorso[userId].getX2(), leftTorso[userId].getY2());
	}

	@Override
	public synchronized void leftWristData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void neckData(float x, float y, float z, int userId,
			int time) {
		neck[userId].setLine(neck[userId].getX1(), neck[userId].getY1(), x, y);
		leftShoulder[userId].setLine(x, y, leftShoulder[userId].getX2(), leftShoulder[userId].getY2());
		rightShoulder[userId].setLine(x, y, rightShoulder[userId].getX2(), rightShoulder[userId]
				.getY2());

	}

	@Override
	public synchronized void rightAnklepData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void rightCollarData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void rightElbowData(float x, float y, float z,
			int userId, int time) {
		rightElbow[userId].setLine(rightElbow[userId].getX1(), rightElbow[userId].getY1(), x, y);
		rightHand[userId].setLine(x, y, rightHand[userId].getX2(), rightHand[userId].getY2());
	}

	@Override
	public synchronized void rightFingertipData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void rightFootData(float x, float y, float z,
			int userId, int time) {
		rightFoot[userId].setLine(rightFoot[userId].getX1(), rightFoot[userId].getY1(), x, y);
	}

	@Override
	public synchronized void rightHandData(float x, float y, float z,
			int userId, int time) {
		rightHand[userId].setLine(rightHand[userId].getX1(), rightHand[userId].getY1(), x, y);
	}

	@Override
	public synchronized void rightHipData(float x, float y, float z,
			int userId, int time) {
		rightHip[userId].setLine(rightHip[userId].getX1(), rightHip[userId].getY1(), x, y);
		rightKnee[userId].setLine(x, y, rightKnee[userId].getX2(), rightKnee[userId].getY2());
		hip[userId].setLine(hip[userId].getX1(), hip[userId].getY1(), x, y);

	}

	@Override
	public synchronized void rightKneeData(float x, float y, float z,
			int userId, int time) {
		rightKnee[userId].setLine(rightKnee[userId].getX1(), rightKnee[userId].getY1(), x, y);
		rightFoot[userId].setLine(x, y, rightFoot[userId].getX2(), rightFoot[userId].getY2());
	}

	@Override
	public synchronized void rightShoulderData(float x, float y, float z,
			int userId, int time) {
		rightShoulder[userId].setLine(rightShoulder[userId].getX1(), rightShoulder[userId].getY1(), x,
				y);
		rightElbow[userId].setLine(x, y, rightElbow[userId].getX2(), rightElbow[userId].getY2());
		rightTorso[userId].setLine(x, y, rightTorso[userId].getX2(), rightTorso[userId].getY2());
	}

	@Override
	public synchronized void rightWristData(float x, float y, float z,
			int userId, int time) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void torsoData(float x, float y, float z, int userId,
			int time) {
		rightTorso[userId].setLine(rightTorso[userId].getX1(), rightTorso[userId].getY1(), x, y);
		leftTorso[userId].setLine(leftTorso[userId].getX1(), leftTorso[userId].getY1(), x, y);
		leftHip[userId].setLine(x, y, leftHip[userId].getX2(), leftHip[userId].getY2());
		rightHip[userId].setLine(x, y, rightHip[userId].getX2(), rightHip[userId].getY2());
	}

	@Override
	public synchronized void waistData(float x, float y, float z, int userId,
			int time) {
		// TODO Auto-generated method stub

	}

	private Line2D normalize(Line2D orig, float maxX, float maxY) {
		double coef = 400f;
		double x1 = (orig.getX1() + coef) / (coef*2);
		double y1 = (orig.getY1() + coef) / (coef*2);
		double x2 = (orig.getX2() + coef) / (coef*2);
		double y2 = (orig.getY2() + coef) / (coef*2);
		Line2D ret = new Line2D.Double(x1 * maxX, maxY - y1 * maxY, x2 * maxX,
				maxY - y2 * maxY);
		return ret;
	}
}
